package com.wxxymaker.edu.utils;

import com.blade.kit.StringKit;
import com.blade.kit.UUID;
import com.wxxymaker.edu.controller.api.FileHandlerApi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * @Author: Soft
 * @Date: 2018/6/29 22:54
 * @Desc: 文件处理工具
 */
public class FileUtils {
    private static final Logger log      = LoggerFactory.getLogger(FileUtils.class);
    private static       String basePath = Const.CLASSPATH.substring(0,
            Const.CLASSPATH.lastIndexOf("/"));
    private static final int    BUFFER   = 16*1024;

    public static void deleteByDownPath(String path, Integer type) {
        String[] typemap = FileHandlerApi.TYPEMAP;
        String kid, fnm;
        if (StringKit.isNotEmpty(path)) {
            if (type == 4) {
                int start = path.indexOf("video/") + 6;
                int end   = path.indexOf("?");
                kid = path.substring(start, end);
                fnm = path.substring(path.indexOf("v=") + 2);
            } else {
                int ks = path.indexOf("k=") + 2;
                int fs = path.indexOf("f=") + 2;
                kid = path.substring(ks, path.indexOf("&", ks));
                int fse = path.indexOf("&", fs);
                fnm = path.substring(fs, fse>0?fse:path.length());
            }

            String webPath = String.format(typemap[type], kid, fnm);
            deleteByWebPath(webPath);
        }
    }

    public static void removeDirOtherFile(String webpath) {
        File file = new File(Const.CLASSPATH, webpath);
        clearFolder(file.getParentFile());
    }

    public static void deleteFolder(File folder) {
        clearFolder(folder);
        folder.delete();
    }

    public static void clearFolder(File folder) {
        File[] listFiles = folder.listFiles();
        if (listFiles != null) {
            for (File file : listFiles) {
                Path toPath = file.toPath();
                try {
                    Files.delete(toPath);
                } catch (IOException e) {
                    log.error("文件删除失败！{}", e.getMessage());
                }
            }
        }
    }

    /**
     * 获取文件名
     * @param path 路径
     */
    public static String getFilename(String path) {
        return path.substring(path.lastIndexOf("/") + 1);
    }

    /**
     * 保存文件
     * @param data 文件数据
     * @param file 文件句柄
     * @throws IOException io异常
     */
    public static Path save(byte[] data, File file) throws IOException {
        if (createFile(file)) {
            return Files.write(file.toPath(), data);
        }
        return null;
    }

    /**
     * 保存文件
     * @param data 文件数据
     * @param path 文件web路径
     * @throws IOException io异常
     */
    public static Path save(byte[] data, String path) throws IOException {
        return save(data, new File(Const.CLASSPATH, path));
    }

    public static void move(File source, String path) throws IOException {
        File target = new File(Const.CLASSPATH, path);
        if (createFile(target)) {
            try (OutputStream out = new FileOutputStream(target);
                  InputStream in = new FileInputStream(source)){
                byte[] bs = new byte[BUFFER];
                int len;
                while ((len = in.read(bs)) != -1) {
                    out.write(bs, 0, len);
                    out.flush();
                }
                source.delete();
            }
        }
    }

    /**
     * 清理临时文件夹
     */
    public static void clearTemp() {
        String readPath = basePath + "/upload/temp/";
        File file = new File(readPath);
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                for (File df : files) {
                    df.delete();
                }
            }
        }
    }


    /**
     * 将文件保存在临时目录
     */
    public static String saveToTemp(byte[] input, String filename) {
        return save(input, "temp", filename);
    }

    /**
     * 将文件保存在指定目录
     * @param input 文件字节数组
     * @param type  类型文件夹
     * @param filename 文件名
     * @return web路径
     */
    public static String saveToUpload(byte[] input, String type, String filename) {
        return save(input, type, filename);
    }

    /**
     * 根据web路径删除文件
     * @param webPath web路径
     */
    public static boolean deleteByWebPath(String webPath) {
        try {
            File file = new File(Const.CLASSPATH, webPath);
            file.delete();
            return true;
        } catch (Exception e) {
            log.error("文件删除失败！WebPath：{} Message：{}", webPath, e.getMessage());
        }
        return false;
    }

    /**
     * 将临时文件移动到目标目录
     * @param tempPaths 临时文件路径
     */
    public static void saveTemp(String... tempPaths) {
        if (StringKit.isNotBlank(tempPaths)) {
            for (String temp : tempPaths) {
                if (temp.startsWith("/temp")) {
                    String target = temp.replace("/temp", "");
                    File targetFile = new File(Const.CLASSPATH, target);
                    if (!targetFile.exists()) {
                        createFile(targetFile);
                    }
                    moveFile(new File(Const.CLASSPATH, temp), targetFile);
                }
            }
        }
    }

    /**
     * 将临时文件移动到目标目录
     * @param temp 临时文件路径
     * @param name 目标文件名 不带类型后缀
     */
    public static void saveTemp(String temp, String name) {
        if (temp.startsWith("/temp")) {
            String target = temp.replace("/temp", "");
            if (StringKit.isNotEmpty(name)) {
                String type = temp.substring(temp.lastIndexOf("."));
                target = target.substring(0, target.lastIndexOf("/") + 1) + name + type;
            }
            File targetFile = new File(Const.CLASSPATH, target);
            if (!targetFile.exists()) {
                createFile(targetFile);
            }
            moveFile(new File(Const.CLASSPATH, temp), targetFile);
        }
    }

    /**
     * 将文件保存在指定目录下
     * @param input    文件输入流
     * @param filename 目标文件名
     * @return 文件web路径
     */
    private static String save(byte[] input, String dir, String filename) {
        String webPath  = "/upload/" + dir + "/" + filename;
        String readPath = basePath + webPath;
        File file = new File(readPath);
        FileOutputStream   out    = null;
        OutputStreamWriter writer = null;
        if (createFile(file)) {
            try {
                out = new FileOutputStream(file);
                if (filename.endsWith(".html")) {
                    writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
                    writer.write(new String(input));
                    writer.flush();
                } else {
                    out.write(input);
                    out.flush();
                }
            } catch (Exception e) {
                log.error("文件保存失败！TargetFile：{} Message：{}", readPath, e.getMessage());
            } finally {
                try {
                    if (out != null) out.close();
                    if (writer != null) writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return webPath;
    }

    public static boolean createFile(File file) {
        if (!file.exists()) {
            file.getParentFile().mkdirs(); // 创建上级目录
            try {
                return file.createNewFile();
            } catch (Exception e) {
                log.error("文件创建失败！FilePath: {}", file.getAbsolutePath());
            }
        }
        return true;
    }

    public static boolean createFolder(File file) {
        if (!file.getParentFile().exists()) {
            return file.getParentFile().mkdirs();
        }
        return true;
    }

    private static void moveFile(File source, File target) {
        FileInputStream  in  = null;
        FileOutputStream out = null;
        try {
            in  = new FileInputStream(source);
            out = new FileOutputStream(target);

            byte[] bs = new byte[1024*16];
            int len = 0;
            while ((len = in.read(bs)) != -1) {
                out.write(bs, 0, len);
            }

            out.flush();
        } catch (Exception e) {
            log.error("文件移动失败--> {}", e.getMessage());
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                    source.delete();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String getRandomFilename(String filename) {
        String name = UUID.captchaChar(14);
        String type = filename.substring(filename.lastIndexOf("."));
        return name + type;
    }
}
